package com.sduept.nwld.dataserver.manager.etl;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
@Slf4j
public class DoubleUtil {
	private static final int DIV_SCALE = 10;// 默认除法运算精度

	private DoubleUtil() {

	}

	/**
	 * 提供精确的加法运算
	 * 
	 * @param v1
	 *            被加数
	 * @param v2
	 *            加数
	 * @return 两个参数的和
	 */
	public static double add(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.add(b2).doubleValue();
	}
	
	public static double[] getDoubleArray4Strs(String str){
		String[] sa = str.split(",");
		double[] rtn = new double[sa.length];
		for (int i = 0; i < rtn.length; i++) {
			rtn[i] = Double.valueOf(sa[i]);
		}
		return rtn;
	}

	/**
	 * 提供精确的减法运算
	 * 
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static double sub(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.subtract(b2).doubleValue();
	}

	/**
	 * 提供精确的乘法运算
	 * 
	 * @param v1
	 *            被乘数
	 * @param v2
	 *            乘数
	 * @return 两个参数的积
	 */
	public static double mul(double v1, double v2) {
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.multiply(b2).doubleValue();
	}

	/**
	 * 提供(相对)精确的除法运算 当除不尽时，使用默认精度：DIV_SCALE
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @return 两个参数的商
	 */
	public static double div(double v1, double v2) {
		return div(v1, v2, DIV_SCALE);
	}

	/**
	 * 提供(相对)精确的除法运算 当除不尽时，使用参数scale指定精度，进行四舍五入
	 * 
	 * @param v1
	 *            被除数
	 * @param v2
	 *            除数
	 * @param scale
	 *            表示精确到小数点后几位
	 * @return 两个参数的商
	 */
	public static double div(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("scale不能小于0");
		}
		BigDecimal b1 = new BigDecimal(Double.toString(v1));
		BigDecimal b2 = new BigDecimal(Double.toString(v2));
		return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	/**
	 * 提供精确的小数位四舍五入处理
	 * 
	 * @param v
	 *            需要四舍五入的数字
	 * @param scale
	 *            小数点后保留几位
	 * @return 四舍五入后的结果
	 */
	public static double round(double v1, int scale) {

		if (scale < 0) {
			throw new IllegalArgumentException("scale不能小于0");
		}
		BigDecimal b = new BigDecimal(Double.toString(v1));
		BigDecimal one = new BigDecimal("1");
		return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	}

	public static String format(double v1, int scale) {

		String s = String.valueOf(round(v1, scale));
		s = new BigDecimal(s).toPlainString();// 解决科学计算法转换问题

		int k = s.indexOf(".");
		if (k < 0 && scale > 0) {
			s = s + ".0";
			k = s.indexOf(".");
		}

		if (k > 0) {
			int d_scale = (s.length() - (k + 1));
			if (scale > d_scale) {
				for (int i = 0; i < scale - d_scale; i++) {
					s += "0";
				}
			} else if (scale < d_scale) {// 当scale=0时才会出现这种情况
				s = s.substring(0, k);
			}
		}
		return s;
	}
	private static double EARTH_RADIUS = 6378.137;

	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}
	/**
	 * 通过经纬度获取距离(单位：米)
	 * 
	 * @param lng1
	 * @param lat1
	 * @param lng2
	 * @param lat2
	 * @return
	 */
	public static double getDistance( double lng1,double lat1,
			double lng2 ,double lat2) {
		double radLat1 = rad(lat1);
		double radLat2 = rad(lat2);
		double a = radLat1 - radLat2;
		double b = rad(lng1) - rad(lng2);
		double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
				+ Math.cos(radLat1) * Math.cos(radLat2)
				* Math.pow(Math.sin(b / 2), 2)));
		s = s * EARTH_RADIUS;
		s = Math.round(s * 10000d) / 10000d;
		s = s * 1000;
		return s;
	}
	
	
	//x 纬度lat1 lat2  y 经度 lng1 lng2  k=（lng2-lng1）/（lat2-lat1）
	public static double getLineaRequationSlope(double lng1,double lat1,
		double lng2 ,double lat2){
		double radLat1 = rad(lat1);
		double radLat2 = rad(lat2);
		double a = radLat2 - radLat1;
		double b = rad(lng2) - rad(lng1);
		double k  =   -(a/b);
		BigDecimal  d  = new  BigDecimal(k);
		double  result  =  d.setScale(2, RoundingMode.HALF_UP).doubleValue();
		return result;
	} 
	
	
	  public static  double pointToLine(double x1, double y1, double x2, double y2, double x0, double y0) {
           double space = 0;
           double a, b, c;
           a = getDistance(x1, y1, x2, y2);// 线段的长度
           b = getDistance(x1, y1, x0, y0);// (x1,y1)到点的距离
           c = getDistance(x2, y2, x0, y0);// (x2,y2)到点的距离
           if (c <= 0.000001 || b <= 0.000001) {
              space = 0;
              return space;
           }
           if (a <= 0.000001) {
              space = b;
              return space;
           }
           if (c * c >= a * a + b * b) {
              space = b;
              return space;
           }
           if (b * b >= a * a + c * c) {
              space = c;
              return space;
           }
           double p = (a + b + c) / 2;// 半周长
           double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));// 海伦公式求面积
           space = 2 * s / a;// 返回点到线的距离（利用三角形面积公式求高）
           return space;
       }
       
	  /*public static  double pointToLine2(double[] p1, double[] p2, double[] p) {
          double space = 0;
          double a, b, c;
          a = getDistance(p1[0], p1[1], p2[0], p2[1]);// 线段的长度
          log.info(a);
          b = getDistance(p1[0], p1[1], p[0], p[1]);// (x1,y1)到点的距离
          log.info(b);
          c = getDistance(p2[0], p2[1], p[0], p[1]);// (x2,y2)到点的距离
          log.info(c);
          if (c <= 0.000001 || b <= 0.000001) {
             space = 0;
             return space;
          }
          if (a <= 0.000001) {
             space = b;
             return space;
          }
          if (c * c >= a * a + b * b) {
             space = b;
             return space;
          }
          if (b * b >= a * a + c * c) {
             space = c;
             return space;
          }
          double r = (a + b + c) / 2;// 半周长
          double s = Math.sqrt(r* (r - a) * (r - b) * (r - c));// 海伦公式求面积
          space = 2 * s / a;// 返回点到线的距离（利用三角形面积公式求高）
          return space;
      }*/
      
	
	public static void main(String[] args) {
		/*double lng1=107.61915d;
		double lat1=23.29779d;
		double lng2=107.619003d;
		double lat2= 23.298d;*/
		double lng1 = 109.59628;
		double lat1 = 22.50843;
		double lng2 = 109.59239;
		double lat2 = 22.50378;
		double lng3= 109.59605;
		double lat3=22.50535;
		double space=pointToLine(lng1,lat1,lng2,lat2,lng3,lat3);
		log.info("space="+space);
		//k=（lng2-lng1）/（lat2-lat1）
		double line2=getDistance(lng1, lat1, lng2, lat2);
		BigDecimal  line222  = new  BigDecimal(line2);
		double  line22 =  line222.setScale(2, RoundingMode.HALF_UP).doubleValue()*2;
		log.info("line22="+line22);
		log.info(String.valueOf(getLineaRequationSlope(lng1, lat1, lng2, lat2)));
		double k=getLineaRequationSlope(lng1, lat1, lng2, lat2);
		double b=lng1-(lat1*k);
		BigDecimal  bb  = new  BigDecimal(b);
		double  bbb  =  bb.setScale(2, RoundingMode.HALF_UP).doubleValue();
		log.info(String.valueOf(bbb));
		double line=Math.sqrt((lat1*lat1)+((lng1-bbb)*(lng1-bbb)));		
		BigDecimal  line1  = new  BigDecimal(line);
		double  line11  =  line1.setScale(2, RoundingMode.HALF_UP).doubleValue();
		log.info("line1="+line11);
		double sss=(line11*2)*line22;		
		log.info("区域面积为："+sss);
//		double lon1 = 109.59628;
//		double lat1 = 22.50843;
//		double lon2 = 109.59239;
//		double lat2 = 22.50378;
//		log.info(getDistance(lon1, lat1, lon2, lat2));;
	}
}
